import Preparation from '../../shared/preparation.md'
import { Tabs, Tab, PackageManagerTabs } from '@theme';

# React MF

在React中，我们准备了两个进阶示例项目作为参考，分别是：

- `runtime-18-host`：基础项目，用于书写通用业务组件对外暴露，它通常是一些项目的基石。
- `runtime-18-app`：基础项目，用于和其他通用业务组件进行集成，它通常是一些项目的业务逻辑。

详情另见[项目仓库](https://github.com/empjs/emp/tree/v3/demos/react18)

<Preparation />

### 拉取项目仓库

```bash
git clone https://github.com/empjs/emp
```

:::danger 🚨 可能遇到的错误
如果您无法拉取项目至本地，请检查您的网络环境或代理设置是否可以访问github，如果仍不能解决，请联系我们。
:::

### 安装依赖

<PackageManagerTabs command="install" />

安装完依赖后，运行 React 示例项目的前期准备就完成了🎉。

## 运行示例项目

:::warning ⚠️ 注意
在运行示例项目之前，请确保您已经完成了前期准备，并当前目录处于`emp`仓库的根目录下。
:::

### React18 demo

首先进入示例项目的根目录：

```bash
cd demos/react18
```

然后运行代码：
<PackageManagerTabs command="dev" />

运行成功后，您可以访问`http://localhost:1801/`进行查看。

:::warning ⚠️ 注意
若`1801`端口被占用，那么启动的服务可能会使用其他端口，详情请留意控制台的输出日志。
:::

#### 演示效果

当您的代码运行成功之后，它应该是这样子的🤩：<a target='_blank' href='https://emp-demo-react18-app.pages.dev/demos/react18/react-app/dist/'>访问链接</a>

<iframe src="https://emp-demo-react18-app.pages.dev/demos/react18/react-app/dist/"
  style={{width: '100%', height: '200px', border: `20px solid #aaa`, borderRadius: '4px', overflow: 'hidden'}}
  title="mf-host"
></iframe>

## 配置讲解

## runtime-18-app

示例项目根目录：

```bash
cd demos/react18/react-app
```

### EMP项目配置

`emp.config.ts`配置如下:
<iframe src="https://github1s.com/empjs/emp/blob/v3/demos/react18/react-app/emp.config.ts"
  style={{width: '100%', height: '800px', border: `20px solid #aaa`, borderRadius: '4px', overflow: 'hidden'}}
  title="emp.config.ts"
></iframe>

#### pluginRspackEmpShare plugins

`pluginRspackEmpShare` 是新增的EMP插件，主要用来配置Module Federation Runtime的公共依赖 `runtimeLib` ，以及公共的框架依赖`frameworkLib`。[插件详情](/plugin/tool/share)

#### build.polyfill.entryCdn

`EMP 3.1.5`及以后版本新增依赖，这里提供配置在页面头部加载兼容行脚本，以便`减少入口包体积`以及`CDN缓存复用`。[配置详情](/config/build/polyfill)

### 远程模块注册与加载

`src/App.tsx`代码如下:
<iframe src="https://github1s.com/empjs/emp/blob/v3/demos/react18/react-app/src/App.tsx"
  style={{width: '100%', height: '800px', border: `20px solid #aaa`, borderRadius: '4px', overflow: 'hidden'}}
  title="src/App.tsx"
></iframe>

代码中分别引入`reactAdapter`与 `@empjs/share/runtime`
```ts
import {reactAdapter} from '@empjs/share/adapter'
import rt from '@empjs/share/runtime'
```
通过使用 `@empjs/share/runtime` 的 `init` 与 `register` 函数，达到 `初始化远程模块` 与 `增量注册远程模块` 的目的。其中 `reactAdapter` 提供了 `module federation` 共享的`share`配置。

注册模块后，使用 `@empjs/share/runtime` 的 `load` 函数，加载模块中的组件，达到使用远程模块的目的。

:::tip
`@empjs/share/runtime` 提供了远程模块运行时注册的能力，所以在 `emp.config.ts` 中无需再使用 `module federation plugin` 。如果当前项目不需要暴露远程模块，那么入口的异步边界`import()`也可以移除。
:::

:::tip
更多详情见 [pluginRspackEmpShare](/plugin/tool/share) 插件配置。
:::